package org.playground.booking.dao.impl;

import org.hibernate.query.Query;
import org.playground.booking.dao.IBookingDao;
import org.playground.booking.dao.IUserDao;
import org.playground.booking.entity.Booking;
import org.playground.booking.entity.User;
import org.playground.booking.enums.BookingStatusEnum;
import org.playground.booking.utils.CommonUtils;
import org.springframework.stereotype.Repository;

import java.util.Date;
import java.util.List;

/**
 * Created by root on 17-10-28.
 */
@Repository
public class BookingDaoImpl extends AbstractDaoImpl<Booking,Long> implements IBookingDao {


    public List<Booking> getBookingsForPlayground(Long playgroundId, Date from, Date to, int pagenb, int pageidx, BookingStatusEnum... bookingStatusEnums){


        String sql = "from Booking as b " +
                " where b.playground.id =:pgId " +
                " and b.startFrom>=:fromDate " +
                " and b.endAt<=:toDate ";
        Long[] statusList = null;

        if(bookingStatusEnums!=null||bookingStatusEnums.length!=0) {
            statusList = new Long[bookingStatusEnums.length];
            for (int i = 0; i < bookingStatusEnums.length; i++) {
                statusList[i]=bookingStatusEnums[i].getStatusCode();
            }

            sql = "from Booking as b " +
                    " where b.playground.id =:pgId " +
                    " and b.startFrom>=:fromDate " +
                    " and b.endAt<=:toDate " +
                    " and b.bookingStatus.statusCode in (:statusList) ";

        }

        Query query = this.getCurrentSession().createQuery(sql);
        if(pagenb>0){
            query.setFirstResult(pageidx*pagenb);
            query.setMaxResults(pagenb);

        }query.setParameter("pgId",playgroundId);
        query.setParameter("fromDate", from);
        query.setParameter("toDate",to);

        if(bookingStatusEnums!=null||bookingStatusEnums.length!=0) {
            query.setParameterList("statusList",statusList);
        }

        return query.list();
    }

    @Override
    public List<Booking> readBookingForUser(Long userId, int pageNb, int pageSize, BookingStatusEnum... bookingStatusEnums) {
        String hql = "select b from Booking as b " +
                "inner join b.user as u " +
                "where u.id = :userId ";

        Long[] statusList = null;

        if(bookingStatusEnums!=null&&bookingStatusEnums.length!=0) {
            statusList = new Long[bookingStatusEnums.length];
            for (int i = 0; i < bookingStatusEnums.length; i++) {
                statusList[i] = bookingStatusEnums[i].getStatusCode();
            }
            hql = "select b from Booking as b " +
                    " inner join b.user as u " +
                    " where u.id=:userId" +
                    " and b.bookingStatus.statusCode in (:statusList) ";

        }


        Query query = this.getCurrentSession().createQuery(hql);
        query.setParameter("userId",userId);

        if(statusList!=null) {
            query.setParameterList("statusList",statusList);
        }

        query.setFirstResult((pageNb-1)*pageSize).setMaxResults(pageSize);

        return query.list();
    }

    @Override
    public Booking readBookingForUser(Long userId, Long bookingId) {
        String hql = " from Booking as b " +
                " where b.user.id=:userId " +
                " and b.id=:bookingId";
        Query query = this.getCurrentSession().createQuery(hql);
        query.setParameter("userId",userId);
        query.setParameter("bookingId",bookingId);
        List<Booking> bookings = query.list();
        return bookings.size()==0?null:bookings.get(0);
    }

    @Override
    public boolean playgroundAlreadyBooked(Long playgroundId, Date from, Date to) {
        String sql = "select count(b.id) from Booking as b " +
                " inner join b.playground as pg " +
                " where (pg.id =:pgId or pg.parentPlayground.id =:pgId)" +
                " and ((b.startFrom>=:fromDate and b.startFrom<:toDate) " +
                " or (b.endAt>:fromDate and b.endAt<=:toDate)) ";

        Query query = this.getCurrentSession().createQuery(sql);
        query.setParameter("pgId",playgroundId);
        query.setParameter("fromDate", from);
        query.setParameter("toDate",to);

        int count = ((Number)query.uniqueResult()).intValue();

        return count > 0;
    }

    @Override
    public List<Booking> getBookingsForPlayground(Long playgroundId, Date from, Date to, BookingStatusEnum... bookingStatusEnums) {
        String sql = "from Booking as b " +
                " where b.playground.id =:pgId " +
                " and b.startFrom>=:fromDate " +
                " and b.endAt<=:toDate ";
        Long[] statusList = null;

        if(bookingStatusEnums!=null||bookingStatusEnums.length!=0) {
            statusList = new Long[bookingStatusEnums.length];
            for (int i = 0; i < bookingStatusEnums.length; i++) {
                statusList[i]=bookingStatusEnums[i].getStatusCode();
            }

            sql = "from Booking as b " +
                    " where b.playground.id =:pgId " +
                    " and b.startFrom>=:fromDate " +
                    " and b.endAt<=:toDate " +
                    " and b.bookingStatus.statusCode in (:statusList) ";

        }

        Query query = this.getCurrentSession().createQuery(sql);
        query.setParameter("pgId",playgroundId);
        query.setParameter("fromDate", from);
        query.setParameter("toDate",to);

        if(bookingStatusEnums!=null||bookingStatusEnums.length!=0) {
            query.setParameterList("statusList",statusList);
        }

        return query.list();
    }


}
